/* dot plugin internal common routines.


   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include "gml4gtk-plugin.h"

/* Used as a string buffer.  */
static struct obstack str_obstack;

/* Print error messages.  */

static void
dot_error (const char *format, ...)
{
  va_list ap;

  va_start (ap, format);
  fprintf (stderr, "%s: error: ", dot_plugin_common.plugin_name);
  vfprintf (stderr,  format, ap);
  va_end (ap);
  fputc ('\n', stderr);

  return;
}

/* Dump the top graph into file FNAME.  */

static void
dot_dump (char *fname)
{
  FILE *fp;

  if ((fp = fopen (fname, "w")) == NULL)
    {
      dot_plugin_common.error ("failed to open file %s.", fname);
      return;
    }

  /* Put the version information on top.  */
  fprintf (fp, "// Generated by GCC gml4gtk Plugin %s\n" \
               "// %s", dot_plugin_common.version, dot_plugin_common.info);

  g_dump_graph (fp, dot_plugin_common.top_graph);
  fclose (fp);

  return;
}

/* Show the top graph.  */

static void
dot_show (char *fname)
{
  char *cmd;
  pid_t pid;

  cmd = concat (dot_plugin_common.dot_viewer, " ", fname, NULL);
  pid = fork ();
  if (pid == 0)
    {
      system (cmd);
      exit (0);
    }
  free (cmd);

  return;
}

/* Do the common initialization work for each view/dump command.  */

static void
dot_init (void)
{
  g_graph *graph;

  /* Create the top graph.  */
  graph = g_new_graph ("top graph");

  dot_plugin_common.top_graph = graph;

  /* Initialize the string obstack.  */
  gcc_obstack_init (&str_obstack);

  /* Open the temp stream.  */
  dot_plugin_common.stream = open_memstream (&dot_plugin_common.stream_buf,
                                             &dot_plugin_common.stream_buf_size);

  return;
}

/* Do the common cleanup work for each view/dump command.  */

static void
dot_finish (void)
{

  g_free_graph (dot_plugin_common.top_graph);

  obstack_free (&str_obstack, NULL);

  fclose (dot_plugin_common.stream);

  free (dot_plugin_common.stream_buf);

  return;
}

/* Print into the string buffer.  */

static void
dot_buf_print (char *fmt, ...)
{
  va_list ap;

  va_start (ap, fmt);
  obstack_vprintf (&str_obstack, fmt, ap);
  va_end (ap);

  return;
}

/* Finish a string and return the address.  */

static void *
dot_buf_finish (void)
{
  obstack_1grow (&str_obstack, '\0');
  return obstack_finish (&str_obstack);
}

dot_plugin_common_t dot_plugin_common =
{
  /* The plugin name.  */
  "Gml4gtk Plugin",
  /* The plugin version.  */
  "2.8",
  /* The gcc base version.  */
  NULL,
  /* Other information.  */
  NULL,
  /* The name of the viewer tool.  */
  "gml4gtk",
  /* The top graph.  */
  NULL,
  /* Temp file name to dump/view a graph.  */
  "dump-temp.dot",
  /* Temp stream to get gcc dump.  */
  NULL,
  NULL,
  0,
  dot_init,
  dot_finish,
  dot_error,
  dot_dump,
  dot_show,
  dot_buf_print,
  dot_buf_finish
};

/* end */
